﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using Liber;
using Liber.WEB;
using System.Text;

namespace FlashQ.Main
{
    public class IotHelper
    {
        public static IotHelper ins;
        static string ACCESS_ID;
        static string ACCESS_SEC;
        static string REGION;
        static string IOTInstance;
        static string BASE_URL;
        static Dictionary<string, string> PRODUCT_Types = new Dictionary<string, string>();

        public static IotHelper SVC {
            get {
                if (ins == null) {
                    var t = new IotHelper();
                    if (ins == null) {
                        ins = t;
                    }
                }
                return ins;
            }
        }

        public IotHelper() {
            var r = XMLSetting.DefaultSetting.First("IoT");
            var pv = r.Property("Provider");
            var cfg = r.First(pv);
            BASE_URL = cfg.First("BaseUrl").Value;
            ACCESS_ID = cfg.First("AccessID").Value;
            ACCESS_SEC = cfg.First("AccessSec").Value;
            REGION = cfg.First("Region").Value;

            var ps = cfg.All("Product", false);
            foreach(var p in ps) {
                PRODUCT_Types.Add(p.First("Name").Value.ToLower(), p.First("Key").Value);
            }
        }

        /// <summary>
        /// 向IOT设备发送一般指令
        /// </summary>
        /// <returns></returns>
        public string SendCMD(string productType,string dvcName,string msg) {
            //string Action = "Pub";
            //string Formate = "JSON";
            //string IotInstanceId = IOTInstance;
            //byte[] data = Encoding.Unicode.GetBytes(msg.FastJson());
            //StringBuilder msgRaw = new StringBuilder(data.Length * 8);
            //foreach (byte b in data) {
            //    msgRaw.Append(Convert.ToString(b, 2).PadLeft(8,'0'));
            //}
            string MessageContent = Convert.ToBase64String(Encoding.Unicode.GetBytes(msg));
            string ProductKey = PRODUCT_Types[productType.ToLower()];

            //string SignatureMethod = "HMAC-SHA1";
            int SignatureNonce = DateTime.Now.ToUnixTimespan();
            //string SignatureVersion = "1.0";
            string Timestamp = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ");
            string TopicFullName =string.Format("/{0}/{1}/user/get",ProductKey,dvcName);
            //string Version = "2018-01-20";

            var p = new StringBuilder();
            p.AppendFormat("AccessKeyId={0}", ACCESS_ID);
            p.Append("&Action=Pub");
            p.Append("&Format=JSON");
            if (!IOTInstance.IsNull()) {
                p.AppendFormat("&IotInstanceId={0}", IOTInstance);
            }
            p.AppendFormat("&MessageContent={0}", WebUtility.UrlEncode(MessageContent).Replace("%","%25"));
            p.AppendFormat("&ProductKey={0}", ProductKey);
            p.AppendFormat("&RegionId={0}", REGION);
            p.AppendFormat("&SecureTransport={0}", "false");
            p.Append("&SignatureMethod=HMAC-SHA1");
            p.AppendFormat("&SignatureNonce={0}", SignatureNonce);
            p.Append("&SignatureVersion=1.0");
            p.AppendFormat("&Timestamp={0}", WebUtility.UrlEncode(Timestamp).Replace("%", "%25"));
            p.AppendFormat("&TopicFullName={0}", WebUtility.UrlEncode(TopicFullName).Replace("%", "%25"));
            p.Append("&Version=2018-01-20");

            DyObject queryArgs = new DyObject();
            queryArgs.Set("AccessKeyId", ACCESS_ID)
                .Set("Action", "Pub")
                .Set("Format", "JSON")
                .Set("MessageContent", WebUtility.UrlEncode(MessageContent))
                .Set("ProductKey", ProductKey)
                .Set("RegionId", REGION)
                .Set("SecureTransport", "false")
                .Set("SignatureMethod", "HMAC-SHA1")
                .Set("SignatureNonce", SignatureNonce)
                .Set("SignatureVersion", "1.0")
                .Set("Timestamp", WebUtility.UrlEncode(Timestamp))
                .Set("TopicFullName", WebUtility.UrlEncode(TopicFullName))
                .Set("Version", "2018-01-20");
            if (!IOTInstance.IsNull()) {
                queryArgs.Set("IotInstanceId", IOTInstance);
            }

            string strToSign = "GET&%2F&"+ p.ToString().Replace("&","%26");
            strToSign = strToSign.Replace("=", "%3D");
            string Signature = strToSign.HmacSHA1(ACCESS_SEC+"&",true,"utf8");
            queryArgs.Set("Signature", WebUtility.UrlEncode(Signature));
            
            var rtn = WebHelper.RequestFrom(BASE_URL,queryArgs);
            if (rtn != null) {
                return rtn.ReadToStr();
            }
            else {
                return "";
            }
        }

        /// <summary>
        /// 向IOT设备发送一般指令
        /// </summary>
        /// <returns></returns>
        public string SendCMDSync(string productType, string dvcName, string msg) {
            //string Action = "RRPC";
            //string Formate = "JSON";
            //string IotInstanceId = IOTInstance;

            string RequestBase64Byte = Convert.ToBase64String(Encoding.Unicode.GetBytes(msg));
            string ProductKey = PRODUCT_Types[productType.ToLower()];

            //string SignatureMethod = "HMAC-SHA1";
            int SignatureNonce = DateTime.Now.ToUnixTimespan();
            //string SignatureVersion = "1.0";
            string Timestamp = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ");
            string TopicFullName = string.Format("/{0}/{1}/user/get", ProductKey, dvcName);
            //string Version = "2018-01-20";

            var p = new StringBuilder();
            p.AppendFormat("AccessKeyId={0}", ACCESS_ID);
            p.Append("&Action=RRpc");
            p.Append("&DeviceName=" + dvcName);
            p.Append("&Format=JSON");
            if (!IOTInstance.IsNull()) {
                p.AppendFormat("&IotInstanceId={0}", IOTInstance);
            }
            p.AppendFormat("&ProductKey={0}", ProductKey);
            p.AppendFormat("&RegionId={0}", REGION);
            p.AppendFormat("&RequestBase64Byte={0}", WebUtility.UrlEncode(RequestBase64Byte).Replace("%", "%25"));
            p.AppendFormat("&SecureTransport={0}", "false");
            p.Append("&SignatureMethod=HMAC-SHA1");
            p.AppendFormat("&SignatureNonce={0}", SignatureNonce);
            p.Append("&SignatureVersion=1.0");
            p.Append("&Timeout=8000");
            p.AppendFormat("&Timestamp={0}", WebUtility.UrlEncode(Timestamp).Replace("%", "%25"));
            p.AppendFormat("&Topic={0}", WebUtility.UrlEncode(TopicFullName).Replace("%", "%25"));
            p.Append("&Version=2018-01-20");

            DyObject queryArgs = new DyObject();
            queryArgs.Set("AccessKeyId", ACCESS_ID)
                .Set("Action", "RRpc")
                .Set("DeviceName",dvcName)
                .Set("Format", "JSON")
                .Set("ProductKey", ProductKey)
                .Set("RegionId", REGION)
                .Set("RequestBase64Byte", WebUtility.UrlEncode(RequestBase64Byte))
                .Set("SecureTransport", "false")
                .Set("SignatureMethod", "HMAC-SHA1")
                .Set("SignatureNonce", SignatureNonce)
                .Set("SignatureVersion", "1.0")
                .Set("Timeout",8000)
                .Set("Timestamp", WebUtility.UrlEncode(Timestamp))
                .Set("Topic", WebUtility.UrlEncode(TopicFullName))
                .Set("Version", "2018-01-20");
            if (!IOTInstance.IsNull()) {
                queryArgs.Set("IotInstanceId", IOTInstance);
            }

            string strToSign = "GET&%2F&" + p.ToString().Replace("&", "%26");
            strToSign = strToSign.Replace("=", "%3D");
            string Signature = strToSign.HmacSHA1(ACCESS_SEC + "&", true, "utf8");
            queryArgs.Set("Signature", WebUtility.UrlEncode(Signature));

            var rtn = WebHelper.RequestFrom(BASE_URL, queryArgs);
            if (rtn != null) {
                return rtn.ReadToStr();
            }
            else {
                return "";
            }
        }
    }
}
